﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http.Headers;
using System.Net.Http;
using System.Net.Security;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Management;
using System.Runtime.InteropServices;
using System.IO;

namespace LOLBattleQuery
{
    public class LCUHttpHelper
    {
        public LCUHttpHelper()
        {
            this.Connect();
        }

        public string GamePath { get; set; }

        public string WorkingDirectory { get; set; }


        private void Connect()
        {
            if (ClientOnline)
            {
                ServicePointManager.SecurityProtocol = (SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12);
                ServicePointManager.ServerCertificateValidationCallback = ((object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => true);
                List<Tuple<string, uint>> commandLines = LCUHttpHelper.GetCommandLines("LeagueClientUx.exe");
                foreach (var item2 in commandLines)
                {
                    string item = item2.Item1;
                    uint pid = item2.Item2;
                    try
                    {
                        if (string.IsNullOrWhiteSpace(item))
                        {
                            Program.Error("检测到游戏已启动，请使用管理员权限启动本软件！");
                            Program.Info("按下任意键程序退出");
                            Console.ReadKey(true);
                            Environment.Exit(0);
                            continue;
                        }
                        string value = Regex.Match(item, "--remoting-auth-token=(.*?)\"").Groups[1].Value;
                        string value2 = Regex.Match(item, "--app-port=(.*?)\"").Groups[1].Value;
                        if (string.IsNullOrWhiteSpace(value2))
                        {
                            continue;
                        }
                        ThreadPool.QueueUserWorkItem(delegate (object e)
                        {
                            Process processById = Process.GetProcessById((int)pid);
                            processById.WaitForExit(-1);
                            this.connect = false;
                        });
                        if (item == null)
                        {
                            return;
                        }
                        try
                        {
                            string uxpath = Regex.Match(item, "^\"*(.*?)\"*\\s\"*--").Groups[1].Value;
                            var fi = new FileInfo(uxpath);
                            FileInfo[] search = fi.Directory.Parent.GetFiles("League of Legends.exe", SearchOption.AllDirectories);
                            if (search == null)
                            {
                                Program.Error("未找到 League of Legends.exe 文件，观战以及回放功能不可用，请联系开发者解决！");
                            }
                            else if (search.Length == 1)
                            {
                                FileInfo fileInfo = search.FirstOrDefault();
                                GamePath = fileInfo.FullName;
                                WorkingDirectory = fileInfo.DirectoryName;
                            }
                            else
                            {
                                Program.Error("找到多个 League of Legends.exe 文件，观战以及回放功能不可用，请联系开发者解决！");
                            }
                            var handler = new HttpClientHandler();
                            handler.ServerCertificateCustomValidationCallback = delegate { return true; };
                            this.http = new HttpClient(handler);
                            this.http.BaseAddress = new Uri("https://127.0.0.1:" + value2);
                            this.http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes("riot:" + value)));
                            this.connect = true;
                        }
                        catch (Exception ex)
                        {
                            Program.Error($"Failed to connect {ex.Message},item -> {item}");
                        }
                    }
                    catch (Exception ex)
                    {
                        Program.Error($"Failed to connect {ex.Message},item -> {item},pid->" + pid);
                    }
                }

            }
        }


        private static Dictionary<int, string> SgpRegion = new Dictionary<int, string>() {
            { 1, "HN1" },
            { 2, "WT1_NEW" },
            { 3, "HN2" },
            { 4, "HN3" },
            { 5, "HN4_NEW" },
            { 6, "WT2_NEW" },
            { 7, "HN5" },
            { 8, "HN6" },
            { 9, "WT3_NEW" },
            { 10,"HN7" },
            { 11,"HN8" },
            { 12,"WT4_NEW" },
            { 13,"HN9" },
            { 14,"HN10" },
            { 15,"HN11" },
            { 16,"WT5" },
            { 17,"HN12" },
            { 18,"HN13" },
            { 19,"HN14" },
            { 20,"WT6" },
            { 21,"EDU1" },
            { 22,"HN15" },
            { 23,"HN16_NEW" },
            { 24,"HN17" },
            { 25,"HN18_NEW" },
            { 26,"WT7" },
            { 27,"HN19" },
            { 30,"BGP1" },
            { 31,"BGP2" },
            { 999, "JP1" },
            { 1000, "TW2" },
            { 1001, "SG2" },
            { 1002, "KR" },
            { 1003, "NA1" },
            { 1004, "PBE1" },
            { 1005, "VN2" }
        };

        public string GetRegion(int area)
        {
            if (!SgpRegion.ContainsKey(area))
            {
                return null;
            }
            return SgpRegion[area];
        }

        public static Dictionary<string, string> SgpHosts { get; set; }

        public string GetSgp(int area) => GetSgp(area.ToString());

        public string GetSgp(string area)
        {
            if (!SgpHosts.ContainsKey(area))
            {
                return null;
            }
            return SgpHosts[area];
        }

        public bool connect { get; set; }

        public bool ClientOnline
        {
            get
            {
                return Process.GetProcessesByName("LeagueClientUx").Length != 0;
            }
        }

        public HttpClient http { get; set; }

        public Task<HttpResponseMessage> GetAsync(string requestUri)
        {
            bool flag = !this.connect;
            if (flag)
            {
                this.Connect();
            }
            return this.http.GetAsync(requestUri);
        }

        public Task<HttpResponseMessage> PostAsync(string requestUri, string content)
        {
            bool flag = !this.connect;
            if (flag)
            {
                this.Connect();
            }
            return this.http.PostAsync(requestUri, new StringContent(content, Encoding.UTF8, "application/json"));
        }

        private static List<Tuple<string, uint>> GetCommandLines(string processName = "nopad++.exe")
        {
            List<Tuple<string, uint>> list = new List<Tuple<string, uint>>();
            string queryString = "select CommandLine,ProcessId from Win32_Process where Name='" + processName + "'";
            using (ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher(queryString))
            {
                using (ManagementObjectCollection managementObjectCollection = managementObjectSearcher.Get())
                {
                    foreach (ManagementBaseObject managementBaseObject in managementObjectCollection)
                    {
                        ManagementObject managementObject = (ManagementObject)managementBaseObject;
                        list.Add(new Tuple<string, uint>((string)managementObject["CommandLine"], (uint)managementObject["ProcessId"]));
                    }
                }
            }
            return list;
        }

    }
}
